package com.lancoo.ccas53.arrangecourse.rulecheck;

import com.lancoo.ccas53.arrangecourse.entities.BaseRule;
import com.lancoo.ccas53.arrangecourse.entities.ClassHour;
import com.lancoo.ccas53.arrangecourse.entities.TeachingClassUnit;
import com.lancoo.ccas53.arrangecourse.entities.TimeslotRoom;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @Description 跨校区规则检测
 * @Author Fortysun
 * @Date 2023/9/5 17:02
 **/
public class CrossCampusRuleCheck extends RuleCheck implements RuleDecorator{
    //接收父类的规则服务对象
    private RuleService ruleService;
    public CrossCampusRuleCheck(RuleService ruleService, BaseRule baseRule) {
        this.ruleService = ruleService;
        super.baseRule = baseRule;
    }
    /**
     * 检测是否适合分配：
     * 1、判断是否满足课程分散、集中规则
     * 2、判断是否满足教师分散、集中规则
     * 3、判断是否满足教师单日最大节次安排
     * @param teachingClassUnit 教学班排课单元
     * @param continuousList 连上的教室课时分组信息列表
     * @param classHourMap 课表课时map
     * @return
     */
    @Override
    public Boolean isSuitable(TeachingClassUnit teachingClassUnit,
                              LinkedList<TimeslotRoom> continuousList,
                              ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap) {
        //如果上一个增强的规则是符合要求的
        if (ruleService.isSuitable(teachingClassUnit, continuousList, classHourMap)) {
            //进行跨校区规则的检测
            return isCrossCampusSuitable(teachingClassUnit, continuousList, classHourMap);
        }

        return false;
    }

    /**
     * 跨校区排课的规则是否符合要求
     * @param teachingClassUnit
     * @param continuousList
     * @param classHourMap
     * @return
     */
    private Boolean isCrossCampusSuitable(TeachingClassUnit teachingClassUnit,
                          LinkedList<TimeslotRoom> continuousList,
                          ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap) {
        //如果连上的教室课时分组列表信息为空，或者没有内容
        if (continuousList == null || continuousList.isEmpty()) {
//            log.error("#ProhibitClashCheck.isSuitable#:分配的教室课时分组信息列表为空~！！");
            return false;
        }
        //排课单元的教学班id
        Long teachingClassId = teachingClassUnit.getTeachingClassId();
        //教学班上课的教师id，多个以逗号分隔
        String teacherIds = teachingClassUnit.getTeacherIds();
        //教学班上课的学生id, 多个以逗号分隔
        String studentIds = teachingClassUnit.getStudentIds();
        //生成教学班的行政班Id
        String phyClassId = teachingClassUnit.getPhyClassId();

        //获取列表的第一个教室课时分组对象
        TimeslotRoom timeslotRoom = continuousList.get(0);
        //天编号，01周一、02周二。。。以此类推
        String dayNo = timeslotRoom.getDayNo();
        //半天编号，1上午、2下午、3晚上
        Integer periodType = timeslotRoom.getPeriodType();
        //待分配的教室课时分组，所属的校区id
        String campusId = timeslotRoom.getCampusId();
        
        //获取半天内，其他校区的课表数据
//        List<ClassHour> halfDayCampusList = getCurHalfDayOtherCampusList(dayNo, periodType, classHourMap, campusId);
        List<ClassHour> campusList = new ArrayList<>();
        if ("b".equals(baseRule.getCrossCampusRule())) {
            //获取半天内，其他校区的课表数据
            campusList = getCurHalfDayOtherCampusList(teachingClassUnit.getClassWeeks(), dayNo, periodType, classHourMap, campusId);
        } else if ("c".equals(baseRule.getCrossCampusRule())) {
            //获取一天内，其他校区的课表数据
            campusList = getCurOneDayOtherCampusList(teachingClassUnit.getClassWeeks(), dayNo, classHourMap, campusId);
        }else {
            return true;
        }
       
        //跨校区排课，学生教师在同一个半天，在不同校区上课情况的判断
        return !isCrossCampusClash(baseRule.getCrossCampusOption(), teachingClassId,
                teacherIds, studentIds, phyClassId, campusList);
    }

    private List<ClassHour> getCurOneDayOtherCampusList(String week, String curDayNo, ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap, String campusId) {
        //定义返回的列表信息
        List<ClassHour> retList = null;
        retList = getCurDayList(week, curDayNo, classHourMap);

        if (retList != null && !retList.isEmpty()) {
            //3、处理教师上课的集中分散，需要获取与待分配的教室课时分组信息相同的，半天内的数据
            retList = retList.stream()
                    //获取与待分配的教室课时分组信息相同的，半天内的其他校区的数据
                    .filter(classHour -> !classHour.getTimeslotRoom().getCampusId().equals(campusId))
                    .collect(Collectors.toList());
        }

        return retList;
    }

    /**
     * 半天内跨校区上课安排
     * @param crossCampusOption 跨校区排课标识，0不跨校区，即各校区独立排课，1跨校区排课
     * @param teachingClassId 排课单元的教学班id
     * @param teacherIds 待分配给教学班的教室课时分组信息列表
     * @param studentIds 已经生成的课表信息
     * @param phyClassId 教学班包含的行政班id
     * @param halfDayCampusList 当前其他校区，当前半天内的已排课表数据（不包含，
     *                          当前待分配的教室课时分组列表，对应的课时编码所对应的分组）
     * @return
     */
    private Boolean isCrossCampusClash(Integer crossCampusOption,
                                       Long teachingClassId,
                                       String teacherIds,
                                       String studentIds,
                                       String phyClassId,
                                       List<ClassHour> halfDayCampusList) {

        Boolean bRet = false;
        //不跨校区
        if (crossCampusOption.equals(0)) {
            bRet = false;
        } else if (crossCampusOption.equals(1)) {//跨校区
            //如果已排课表没数据，那肯定不管分散和集中都是返回false的
            //因为此时没有对比数据
            if (halfDayCampusList == null || halfDayCampusList.isEmpty()) {
                //没有比较数据，肯定就不存在跨校区的问题
                return false;
            }
            //判断当前其他校区，当前半天内的已排课表数据（不包含，当前待分配的教室课时分组列表，对应的课时编码所对应的分组）
            bRet = isClashes(teachingClassId, teacherIds, studentIds, phyClassId, halfDayCampusList);
        }

        return bRet;
    }
}
